"""
交易执行引擎
============

基于现有的MainTradingEngine设计的高性能交易执行引擎
支持毫秒级订单执行、多网关路由、执行算法优化
"""

# 确保项目根目录在Python路径中

# 统一路径管理
from backend.shared import PathManager
PathManager().setup_paths()
import sys
import os

import asyncio
import logging
from typing import Dict, List, Optional, Any, Callable, Set
from decimal import Decimal
from datetime import datetime, timedelta
from enum import Enum
import uuid
import time
from dataclasses import dataclass, field

from ..models.trading_models import TradingOrder, TradingGateway, OrderStatus, GatewayStatus
from ..schemas.trading_schemas import OrderRequest
from ..core.exceptions import (
    TradingServiceError, GatewayNotConnectedError, OrderValidationError,
    GatewayTimeoutError, ExternalServiceTimeoutError
)
from ..core.events import EventManager, TradingEventType

class ExecutionAlgorithm(str, Enum):
    """执行算法类型"""
    IMMEDIATE = "immediate"          # 立即执行
    TWAP = "twap"                   # 时间加权平均价格
    VWAP = "vwap"                   # 成交量加权平均价格
    ICEBERG = "iceberg"             # 冰山算法
    SMART_ROUTING = "smart_routing"  # 智能路由

class OrderPriority(str, Enum):
    """订单优先级"""
    LOW = "low"
    NORMAL = "normal"
    HIGH = "high"
    URGENT = "urgent"

@dataclass
class ExecutionContext:
    """执行上下文"""
    order_id: str
    user_id: str
    algorithm: ExecutionAlgorithm
    priority: OrderPriority
    gateway_preference: Optional[str] = None
    max_execution_time: Optional[int] = None  # 秒
    slice_size: Optional[Decimal] = None
    slice_interval: Optional[float] = None    # 秒
    created_at: datetime = field(default_factory=datetime.utcnow)
    
    # 执行状态
    is_active: bool = True
    executed_volume: Decimal = Decimal('0')
    remaining_volume: Decimal = Decimal('0')
    average_price: Decimal = Decimal('0')
    
    # 性能指标
    start_time: Optional[datetime] = None
    end_time: Optional[datetime] = None
    execution_latency: Optional[float] = None  # 毫秒
    gateway_latencies: Dict[str, float] = field(default_factory=dict)

@dataclass
class GatewayConnection:
    """网关连接信息"""
    gateway_name: str
    gateway_type: str
    status: GatewayStatus
    last_ping_time: Optional[datetime] = None
    latency_ms: Optional[float] = None
    error_count: int = 0
    success_count: int = 0
    
    # 连接配置
    max_orders_per_second: int = 10
    timeout_seconds: int = 30
    
    # 统计信息
    total_orders: int = 0
    successful_orders: int = 0
    failed_orders: int = 0
    
    @property
    def success_rate(self) -> float:
        """成功率"""
        if self.total_orders == 0:
            return 0.0
        return self.successful_orders / self.total_orders
    
    @property
    def is_healthy(self) -> bool:
        """是否健康"""
        return (
            self.status == GatewayStatus.CONNECTED and
            self.success_rate >= 0.8 and
            self.error_count < 10 and
            (self.latency_ms is None or self.latency_ms < 1000)
        )

class TradingExecutionEngine:
    """
    交易执行引擎
    
    基于现有的MainTradingEngine架构设计
    提供高性能的订单执行和智能路由功能
    """
    
    def __init__(self, event_manager: EventManager):
        self.event_manager = event_manager
        self.logger = logging.getLogger(__name__)
        
        # 网关管理
        self._gateways: Dict[str, GatewayConnection] = {}
        self._gateway_locks: Dict[str, asyncio.Lock] = {}
        
        # 执行管理
        self._execution_contexts: Dict[str, ExecutionContext] = {}
        self._execution_tasks: Dict[str, asyncio.Task] = {}
        self._execution_queue: asyncio.PriorityQueue = asyncio.PriorityQueue()
        
        # 路由管理
        self._routing_rules: Dict[str, List[str]] = {}  # symbol -> gateway_names
        self._load_balancer: Dict[str, int] = {}  # gateway_name -> current_load
        
        # 性能监控
        self._performance_metrics = {
            "total_orders": 0,
            "successful_orders": 0,
            "failed_orders": 0,
            "average_latency": 0.0,
            "max_latency": 0.0,
            "min_latency": float('inf')
        }
        
        # 执行引擎状态
        self._is_running = False
        self._worker_tasks: List[asyncio.Task] = []
        self._max_workers = 10
        
        self.logger.info("交易执行引擎初始化完成")
    
    async def start(self):
        """启动执行引擎"""
        if self._is_running:
            return
        
        self._is_running = True
        
        # 启动工作线程
        for i in range(self._max_workers):
            task = asyncio.create_task(self._execution_worker(f"worker-{i}"))
            self._worker_tasks.append(task)
        
        # 启动网关健康检查
        health_check_task = asyncio.create_task(self._gateway_health_checker())
        self._worker_tasks.append(health_check_task)
        
        # 启动性能监控
        metrics_task = asyncio.create_task(self._metrics_collector())
        self._worker_tasks.append(metrics_task)
        
        self.logger.info("交易执行引擎已启动")
    
    async def stop(self):
        """停止执行引擎"""
        if not self._is_running:
            return
        
        self._is_running = False
        
        # 取消所有执行任务
        for task in self._execution_tasks.values():
            if not task.done():
                task.cancel()
        
        # 取消工作线程
        for task in self._worker_tasks:
            if not task.done():
                task.cancel()
        
        # 等待所有任务完成
        if self._worker_tasks:
            await asyncio.gather(*self._worker_tasks, return_exceptions=True)
        
        self.logger.info("交易执行引擎已停止")
    
    async def register_gateway(self, gateway: TradingGateway) -> bool:
        """注册交易网关"""
        try:
            connection = GatewayConnection(
                gateway_name=gateway.gateway_name,
                gateway_type=gateway.gateway_type,
                status=gateway.status
            )
            
            self._gateways[gateway.gateway_name] = connection
            self._gateway_locks[gateway.gateway_name] = asyncio.Lock()
            self._load_balancer[gateway.gateway_name] = 0
            
            self.logger.info(f"网关注册成功: {gateway.gateway_name}")
            return True
            
        except Exception as e:
            self.logger.error(f"网关注册失败: {e}")
            return False
    
    async def unregister_gateway(self, gateway_name: str) -> bool:
        """注销交易网关"""
        try:
            if gateway_name in self._gateways:
                del self._gateways[gateway_name]
                del self._gateway_locks[gateway_name]
                del self._load_balancer[gateway_name]
                
                self.logger.info(f"网关注销成功: {gateway_name}")
                return True
            
            return False
            
        except Exception as e:
            self.logger.error(f"网关注销失败: {e}")
            return False
    
    async def execute_order(self, order: TradingOrder, 
                          algorithm: ExecutionAlgorithm = ExecutionAlgorithm.IMMEDIATE,
                          priority: OrderPriority = OrderPriority.NORMAL,
                          gateway_preference: Optional[str] = None) -> str:
        """
        执行订单
        
        Args:
            order: 交易订单
            algorithm: 执行算法
            priority: 订单优先级
            gateway_preference: 首选网关
            
        Returns:
            执行上下文ID
        """
        try:
            # 创建执行上下文
            context = ExecutionContext(
                order_id=order.order_id,
                user_id=order.user_id,
                algorithm=algorithm,
                priority=priority,
                gateway_preference=gateway_preference,
                remaining_volume=order.volume
            )
            
            context_id = str(uuid.uuid4())
            self._execution_contexts[context_id] = context
            
            # 验证订单
            await self._validate_order(order)
            
            # 选择执行策略
            if algorithm == ExecutionAlgorithm.IMMEDIATE:
                await self._execute_immediate(context_id, order)
            elif algorithm == ExecutionAlgorithm.TWAP:
                await self._execute_twap(context_id, order)
            elif algorithm == ExecutionAlgorithm.VWAP:
                await self._execute_vwap(context_id, order)
            elif algorithm == ExecutionAlgorithm.ICEBERG:
                await self._execute_iceberg(context_id, order)
            elif algorithm == ExecutionAlgorithm.SMART_ROUTING:
                await self._execute_smart_routing(context_id, order)
            else:
                raise OrderValidationError(f"不支持的执行算法: {algorithm}")
            
            self.logger.info(f"订单执行启动: {order.order_id}, 算法: {algorithm}")
            return context_id
            
        except Exception as e:
            self.logger.error(f"订单执行失败: {e}")
            raise
    
    async def cancel_execution(self, context_id: str) -> bool:
        """取消订单执行"""
        try:
            if context_id not in self._execution_contexts:
                return False
            
            context = self._execution_contexts[context_id]
            context.is_active = False
            
            # 取消执行任务
            if context_id in self._execution_tasks:
                task = self._execution_tasks[context_id]
                if not task.done():
                    task.cancel()
                del self._execution_tasks[context_id]
            
            self.logger.info(f"订单执行已取消: {context.order_id}")
            return True
            
        except Exception as e:
            self.logger.error(f"取消订单执行失败: {e}")
            return False
    
    async def get_execution_status(self, context_id: str) -> Optional[Dict[str, Any]]:
        """获取执行状态"""
        if context_id not in self._execution_contexts:
            return None
        
        context = self._execution_contexts[context_id]
        
        return {
            "context_id": context_id,
            "order_id": context.order_id,
            "algorithm": context.algorithm,
            "priority": context.priority,
            "is_active": context.is_active,
            "executed_volume": str(context.executed_volume),
            "remaining_volume": str(context.remaining_volume),
            "average_price": str(context.average_price),
            "execution_latency": context.execution_latency,
            "start_time": context.start_time,
            "end_time": context.end_time
        }
    
    async def _validate_order(self, order: TradingOrder):
        """验证订单"""
        if order.volume <= 0:
            raise OrderValidationError("订单数量必须大于0")
        
        if order.order_type.value == "LIMIT" and order.price <= 0:
            raise OrderValidationError("限价单价格必须大于0")
        
        # 检查可用网关
        available_gateways = self._get_available_gateways(order.symbol, order.exchange)
        if not available_gateways:
            raise GatewayNotConnectedError(f"没有可用的网关处理合约: {order.symbol}.{order.exchange}")
    
    def _get_available_gateways(self, symbol: str, exchange: str) -> List[str]:
        """获取可用网关列表"""
        available = []
        
        for gateway_name, connection in self._gateways.items():
            if connection.is_healthy:
                # 检查路由规则
                symbol_key = f"{symbol}.{exchange}"
                if symbol_key in self._routing_rules:
                    if gateway_name in self._routing_rules[symbol_key]:
                        available.append(gateway_name)
                else:
                    # 没有特定路由规则，使用所有健康网关
                    available.append(gateway_name)
        
        return available
    
    def _select_optimal_gateway(self, available_gateways: List[str], 
                              preference: Optional[str] = None) -> str:
        """选择最优网关"""
        if not available_gateways:
            raise GatewayNotConnectedError("没有可用的网关")
        
        # 如果指定了首选网关且可用，直接使用
        if preference and preference in available_gateways:
            return preference
        
        # 根据负载均衡选择网关
        best_gateway = min(available_gateways, 
                          key=lambda g: self._load_balancer.get(g, 0))
        
        return best_gateway
    
    async def _execute_immediate(self, context_id: str, order: TradingOrder):
        """立即执行算法"""
        context = self._execution_contexts[context_id]
        context.start_time = datetime.utcnow()
        
        # 选择网关
        available_gateways = self._get_available_gateways(order.symbol, order.exchange)
        gateway_name = self._select_optimal_gateway(available_gateways, context.gateway_preference)
        
        # 创建执行任务
        task = asyncio.create_task(
            self._submit_order_to_gateway(context_id, order, gateway_name)
        )
        self._execution_tasks[context_id] = task
    
    async def _execute_twap(self, context_id: str, order: TradingOrder):
        """时间加权平均价格算法"""
        context = self._execution_contexts[context_id]
        context.start_time = datetime.utcnow()
        
        # TWAP算法参数
        total_time = context.max_execution_time or 300  # 默认5分钟
        slice_count = 10  # 分割成10个子订单
        slice_size = order.volume / slice_count
        slice_interval = total_time / slice_count
        
        context.slice_size = slice_size
        context.slice_interval = slice_interval
        
        # 创建执行任务
        task = asyncio.create_task(
            self._execute_sliced_order(context_id, order, slice_size, slice_interval)
        )
        self._execution_tasks[context_id] = task
    
    async def _execute_vwap(self, context_id: str, order: TradingOrder):
        """成交量加权平均价格算法"""
        # VWAP算法的具体实现
        # 这里简化为TWAP处理
        await self._execute_twap(context_id, order)
    
    async def _execute_iceberg(self, context_id: str, order: TradingOrder):
        """冰山算法"""
        context = self._execution_contexts[context_id]
        context.start_time = datetime.utcnow()
        
        # 冰山算法参数
        visible_size = context.slice_size or (order.volume * Decimal('0.1'))  # 显示10%
        
        # 创建执行任务
        task = asyncio.create_task(
            self._execute_iceberg_order(context_id, order, visible_size)
        )
        self._execution_tasks[context_id] = task
    
    async def _execute_smart_routing(self, context_id: str, order: TradingOrder):
        """智能路由算法"""
        context = self._execution_contexts[context_id]
        context.start_time = datetime.utcnow()
        
        # 智能路由：同时向多个网关发送小额订单
        available_gateways = self._get_available_gateways(order.symbol, order.exchange)
        
        if len(available_gateways) > 1:
            # 分散到多个网关
            slice_size = order.volume / len(available_gateways)
            tasks = []
            
            for gateway_name in available_gateways:
                task = asyncio.create_task(
                    self._submit_partial_order(context_id, order, gateway_name, slice_size)
                )
                tasks.append(task)
            
            # 等待所有任务完成
            combined_task = asyncio.create_task(asyncio.gather(*tasks, return_exceptions=True))
            self._execution_tasks[context_id] = combined_task
        else:
            # 只有一个网关，使用立即执行
            await self._execute_immediate(context_id, order)
    
    async def _execute_sliced_order(self, context_id: str, order: TradingOrder, 
                                   slice_size: Decimal, slice_interval: float):
        """执行分片订单"""
        context = self._execution_contexts[context_id]
        
        while context.is_active and context.remaining_volume > 0:
            # 计算当前切片大小
            current_slice = min(slice_size, context.remaining_volume)
            
            # 选择网关
            available_gateways = self._get_available_gateways(order.symbol, order.exchange)
            gateway_name = self._select_optimal_gateway(available_gateways)
            
            # 提交切片订单
            await self._submit_partial_order(context_id, order, gateway_name, current_slice)
            
            # 等待间隔
            if context.remaining_volume > 0:
                await asyncio.sleep(slice_interval)
        
        context.end_time = datetime.utcnow()
        if context.start_time:
            context.execution_latency = (context.end_time - context.start_time).total_seconds() * 1000
    
    async def _execute_iceberg_order(self, context_id: str, order: TradingOrder, 
                                    visible_size: Decimal):
        """执行冰山订单"""
        context = self._execution_contexts[context_id]
        
        while context.is_active and context.remaining_volume > 0:
            # 计算可见大小
            current_visible = min(visible_size, context.remaining_volume)
            
            # 选择网关
            available_gateways = self._get_available_gateways(order.symbol, order.exchange)
            gateway_name = self._select_optimal_gateway(available_gateways)
            
            # 提交可见部分
            await self._submit_partial_order(context_id, order, gateway_name, current_visible)
            
            # 等待当前订单完成或部分成交
            await asyncio.sleep(1)  # 简化处理
        
        context.end_time = datetime.utcnow()
        if context.start_time:
            context.execution_latency = (context.end_time - context.start_time).total_seconds() * 1000
    
    async def _submit_order_to_gateway(self, context_id: str, order: TradingOrder, 
                                     gateway_name: str) -> bool:
        """向网关提交订单"""
        start_time = time.time()
        
        try:
            # 获取网关锁
            async with self._gateway_locks[gateway_name]:
                # 更新负载
                self._load_balancer[gateway_name] += 1
                
                # 模拟网关提交
                gateway = self._gateways[gateway_name]
                gateway.total_orders += 1
                
                # 模拟网络延迟
                await asyncio.sleep(0.001)  # 1毫秒
                
                # 模拟成功率
                if gateway.success_rate > 0.9:  # 90%成功率
                    gateway.successful_orders += 1
                    
                    # 更新执行上下文
                    context = self._execution_contexts[context_id]
                    context.executed_volume = order.volume
                    context.remaining_volume = Decimal('0')
                    context.end_time = datetime.utcnow()
                    
                    # 计算延迟
                    latency = (time.time() - start_time) * 1000
                    context.execution_latency = latency
                    context.gateway_latencies[gateway_name] = latency
                    
                    # 发布执行成功事件
                    await self.event_manager.publish(TradingEventType.ORDER_EXECUTED, {
                        "order_id": order.order_id,
                        "gateway": gateway_name,
                        "volume": str(order.volume),
                        "latency_ms": latency
                    })
                    
                    self._update_performance_metrics(latency, True)
                    return True
                else:
                    gateway.failed_orders += 1
                    gateway.error_count += 1
                    
                    self._update_performance_metrics(0, False)
                    raise ExternalServiceTimeoutError(gateway_name, 30)
                
        except Exception as e:
            self.logger.error(f"向网关提交订单失败: {gateway_name}, {e}")
            
            # 更新网关错误计数
            if gateway_name in self._gateways:
                self._gateways[gateway_name].error_count += 1
            
            raise
        finally:
            # 减少负载
            if gateway_name in self._load_balancer:
                self._load_balancer[gateway_name] = max(0, self._load_balancer[gateway_name] - 1)
    
    async def _submit_partial_order(self, context_id: str, order: TradingOrder, 
                                   gateway_name: str, volume: Decimal) -> bool:
        """提交部分订单"""
        # 创建部分订单副本
        partial_order = TradingOrder(
            id=str(uuid.uuid4()),
            order_id=f"{order.order_id}_partial_{int(time.time())}",
            user_id=order.user_id,
            symbol=order.symbol,
            exchange=order.exchange,
            direction=order.direction,
            offset=order.offset,
            order_type=order.order_type,
            volume=volume,
            price=order.price,
            remaining_volume=volume
        )
        
        return await self._submit_order_to_gateway(context_id, partial_order, gateway_name)
    
    async def _execution_worker(self, worker_name: str):
        """执行工作线程"""
        self.logger.info(f"执行工作线程启动: {worker_name}")
        
        while self._is_running:
            try:
                # 从队列获取执行任务
                priority, timestamp, context_id = await asyncio.wait_for(
                    self._execution_queue.get(), timeout=1.0
                )
                
                # 处理执行任务
                if context_id in self._execution_contexts:
                    context = self._execution_contexts[context_id]
                    self.logger.debug(f"处理执行任务: {context.order_id}")
                
            except asyncio.TimeoutError:
                continue
            except Exception as e:
                self.logger.error(f"执行工作线程异常: {worker_name}, {e}")
                await asyncio.sleep(1)
        
        self.logger.info(f"执行工作线程停止: {worker_name}")
    
    async def _gateway_health_checker(self):
        """网关健康检查"""
        while self._is_running:
            try:
                for gateway_name, connection in self._gateways.items():
                    # 模拟健康检查
                    start_time = time.time()
                    
                    # 模拟ping
                    await asyncio.sleep(0.001)
                    
                    latency = (time.time() - start_time) * 1000
                    connection.latency_ms = latency
                    connection.last_ping_time = datetime.utcnow()
                    
                    # 根据延迟和错误率更新状态
                    if latency < 100 and connection.error_count < 5:
                        connection.status = GatewayStatus.CONNECTED
                    else:
                        connection.status = GatewayStatus.ERROR
                
                await asyncio.sleep(30)  # 30秒检查一次
                
            except Exception as e:
                self.logger.error(f"网关健康检查异常: {e}")
                await asyncio.sleep(30)
    
    async def _metrics_collector(self):
        """性能指标收集器"""
        while self._is_running:
            try:
                # 收集性能指标
                total_orders = sum(g.total_orders for g in self._gateways.values())
                successful_orders = sum(g.successful_orders for g in self._gateways.values())
                
                self._performance_metrics.update({
                    "total_orders": total_orders,
                    "successful_orders": successful_orders,
                    "failed_orders": total_orders - successful_orders,
                    "success_rate": successful_orders / max(total_orders, 1)
                })
                
                await asyncio.sleep(60)  # 1分钟收集一次
                
            except Exception as e:
                self.logger.error(f"性能指标收集异常: {e}")
                await asyncio.sleep(60)
    
    def _update_performance_metrics(self, latency: float, success: bool):
        """更新性能指标"""
        if success:
            self._performance_metrics["successful_orders"] += 1
            
            # 更新延迟统计
            current_avg = self._performance_metrics["average_latency"]
            total = self._performance_metrics["total_orders"]
            new_avg = (current_avg * total + latency) / (total + 1)
            
            self._performance_metrics["average_latency"] = new_avg
            self._performance_metrics["max_latency"] = max(
                self._performance_metrics["max_latency"], latency
            )
            self._performance_metrics["min_latency"] = min(
                self._performance_metrics["min_latency"], latency
            )
        else:
            self._performance_metrics["failed_orders"] += 1
        
        self._performance_metrics["total_orders"] += 1
    
    def get_performance_metrics(self) -> Dict[str, Any]:
        """获取性能指标"""
        return self._performance_metrics.copy()
    
    def get_gateway_status(self) -> Dict[str, Dict[str, Any]]:
        """获取网关状态"""
        status = {}
        for name, connection in self._gateways.items():
            status[name] = {
                "status": connection.status.value,
                "latency_ms": connection.latency_ms,
                "success_rate": connection.success_rate,
                "total_orders": connection.total_orders,
                "load": self._load_balancer.get(name, 0),
                "is_healthy": connection.is_healthy
            }
        return status